package ru.evga.gwt.lib.common.client.view;

import ru.evga.gwt.lib.common.client.domain.BaseEntityDto;

import com.google.gwt.cell.client.ButtonCell;
import com.google.gwt.cell.client.Cell;
import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.HasData;


/**
 * Abstract implementation of IEntityListView.
 * 
 * @param <E> entity
 */
public abstract class AbstractEntityListView<E extends BaseEntityDto>
    extends Composite
    implements IEntityListView<E>
{
    private HasData<E> display;
    private IEntityListView.Delegate<E> delegate;

    
    private static interface GetValue<T, C>
    {
        C getValue(T city);
    }

    
    public HasData<E> asHasData()
    {
        return display;
    }

    @Override
    public AbstractEntityListView<E> asWidget()
    {
        return this;
    }

    public void setDelegate(final Delegate<E> delegate)
    {
        this.delegate = delegate;
    }

    protected Delegate<E> getDelegate()
    {
        return this.delegate;
    }

    protected void init(Widget root, HasData<E> display)
    {
        super.initWidget(root);
        this.display = display;
    }

    protected void initWidget(Widget widget)
    {
        throw new UnsupportedOperationException("AbstractEntityListView must be initialized via "
            + "init(Widget, HasData<P>, Button) ");
    }

    
    // ButtonCell.
    protected void addEditColumn(CellTable<E> table)
    {
        addColumn(table, new ButtonCell(), "Edit", new GetValue<E, String>()
        {
            public String getValue(E data)
            {
                return "Edit";
            }
        }, new FieldUpdater<E, String>()
        {
            public void update(int index, E object, String value)
            {
                getDelegate().onEditClicked(object);
            }
        });
    }
    
    protected void addRemoveColumn(CellTable<E> table)
    {
        addColumn(table, new ButtonCell(), "Remove", new GetValue<E, String>()
        {
            public String getValue(E data)
            {
                return "Remove";
            }
        }, new FieldUpdater<E, String>()
        {
            public void update(int index, E object, String value)
            {
                getDelegate().onRemoveClicked(object);
            }
        });
    }
//    // ButtonCell.
//    protected void  addColumn(new ButtonCell(), "Delete", new GetValue<String>()
//    {
//        public String getValue(CityDto city)
//        {
//            return "Delete";
//        }
//    }, new FieldUpdater<CityDto, String>()
//    {
//        public void update(int index, CityDto object, String value)
//        {
//            getDelegate().onRemoveClicked(object);
//        }
//    });

    
    private <C> void addColumn(CellTable<E> table, Cell<C> cell, String headerText, final GetValue<E, C> getter,
        FieldUpdater<E, C> fieldUpdater)
    {
        Column<E, C> column = new Column<E, C>(cell)
        {
            @Override
            public C getValue(E object)
            {
                return getter.getValue(object);
            }
        };
        column.setFieldUpdater(fieldUpdater);
        table.addColumn(column, headerText);
    }

}
